%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%  Copyright by Wenliang Du.                                       %%
%%  This work is licensed under the Creative Commons                %%
%%  Attribution-NonCommercial-ShareAlike 4.0 International License. %%
%%  To view a copy of this license, visit                           %%
%%  http://creativecommons.org/licenses/by-nc-sa/4.0/.              %%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

\newcommand{\commonfolder}{../../common-files}
\newcommand{\webcommon}{../Web_Common}

\input{\commonfolder/header}
\input{\commonfolder/copyright}


\newcommand{\bash}{{\tt bash}\xspace}
\newcommand{\Bash}{{\tt Bash}\xspace}

\lhead{\bfseries SEED 实验 -- Shellshock 攻击实验}

\begin{document}

\begin{center}
{\LARGE Shellshock 攻击实验}
\end{center}

\seedlabcopyright{2006 - 2016}

\section{概述}

2014年9月24日，bash 中的一个严重漏洞被发现了。这个漏洞被称为 Shellshock，很多系统受到影响。在本实验中，学生需要进行这个攻击，以便深入了解 Shellshock 漏洞。这个实验的学习目标是让学生通过亲身体验这个有趣的攻击，理解它是如何工作的，并思考从中可以得到的教训。这个实验的第一个版本是在 2014 年9月29日开发的，距漏洞报告发布仅五天。SEED项目的一个重要任务是快速将实际攻击转化为教育材料，以便教师能及时将它们引入课堂，并让学生关注现实世界中的事件。本实验包含以下主题：

\begin{itemize}[noitemsep]
\item Shellshock
\item 环境变量
\item bash中的函数定义
\item Apache和CGI程序
\end{itemize}


\paragraph{阅读和视频。}
关于Shellshock攻击的详细信息可以在以下资料中找到：

\begin{itemize}
\item SEED 教科书的第3章，\seedbook
\item SEED 课程视频的第3节，\seedcsvideo
\end{itemize}


\paragraph{实验环境。} \seedenvironmentB \nodependency



% *******************************************
% SECTION
% *******************************************
\section{环境设置} 



% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{DNS设置}

在我们的设置中，Web 服务器容器的 IP 地址是 \texttt{10.9.0.5}，主机名是
\texttt{www.seed-server.com}，我们需要将这个主机名和 IP 地址的映射添加到
\texttt{/etc/hosts} 文件中。需要使用root权限来修改该文件： 

\begin{lstlisting}
10.9.0.5       www.seed-server.com
\end{lstlisting}
 


% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{容器设置和命令}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{\commonfolder/container/setup}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


% -------------------------------------------
% SUBSECTION
% -------------------------------------------
\subsection{Web服务器和CGI}

在本实验中，我们将对 Web 服务器发起 Shellshock 攻击。许多 Web 服务器都用了 CGI，这是 Web 应用程序中生成动态内容的常用方法。许多 CGI 程序是 shell 脚本，因此在 CGI 程序运行之前，shell 程序会先运行。这种调用是由远程计算机的用户触发的，如果该 shell 程序是一个存在漏洞的 bash 程序，那么我们就可以利用 Shellshock 漏洞来获取服务器上的权限。

在我们的 Web 服务器中已经设置了一个非常简单的 CGI 程序 \texttt{vul.cgi}）， 它是个 shell 脚本，功能就是打印出 {\tt "Hello World"}。该 CGI 程序放在 Apache 的默认 CGI 文件夹\texttt{/usr/lib/cgi-bin} 中，它必须设置成可执行的。

\begin{lstlisting}[caption=\texttt{vul.cgi}] 
(*@\textbf{\#!/bin/bash\_shellshock}@*)          

echo "Content-type: text/plain"
echo
echo
echo "Hello World"
\end{lstlisting}

该 CGI 程序使用 \texttt{/bin/bash\_shellshock}（第一行），而不是使用\texttt{/bin/bash}。这一行指定应当调用哪个 shell 程序来运行脚本。在本实验中，我们需要使用有漏洞的 bash 程序。

要从 Web 访问 CGI 程序，我们可以通过浏览器输入以下URL: \url{http://www.seed-server.com/cgi-bin/vul.cgi}， 或者使用以下命令行程序 {\tt curl} 来执行相同操作。

\begin{lstlisting}
$ curl http://www.seed-server.com/cgi-bin/vul.cgi
\end{lstlisting}


% *******************************************
% SECTION
% ******************************************* 
\section{实验任务}

关于 Shellshock 攻击的详细指导可以在网上或 SEED 书中找到，我们不会在实验描述中重复这些内容。 

% -------------------------------------------
% SUBSECTION
% ------------------------------------------- 
\subsection{任务 1: 实验 Bash 函数}

Ubuntu 20.04 中的 bash 程序已经打了补丁，因此它不再有 Shellshock 漏洞。为了本实验的目的，
我们在容器中安装了一个有漏洞的 bash 版本（在\texttt{/bin}中）。该程序也可以在\texttt{Labsetup}文件夹（在\texttt{image\_www}中）找到。它的名字是 \texttt{bash\_shellshock}。我们需要使用
这个 bash 程序来完成任务。你可以在容器中或直接在你的计算机上运行这个shell程序。

请设计一个实验来验证该 bash 程序是否容易受到 Shellshock 攻击。在已打了补丁的版本 \texttt{/bin/bash} 上进行相同的实验并报告你的观察结果。

% -------------------------------------------
% SUBSECTION
% ------------------------------------------- 
\subsection{任务 2: 通过环境变量传递数据给Bash}

要利用 Shellshock 漏洞，攻击者需要将数据传递给有漏洞的 bash 程序，而且这些数据必须要通过
环境变量传递。在这个任务中，我们看看如何实现这一目标。我们在服务器上提供了另一个 CGI 程序（\texttt{getenv.cgi}）来帮助你识别哪些用户数据可以进入 CGI 程序的环境变量。该 CGI 程序会打印出它的所有环境变量。 

\begin{lstlisting}[caption=\texttt{getenv.cgi}]
#!/bin/bash_shellshock             

echo "Content-type: text/plain"
echo
echo "****** Environment Variables ******"
strings /proc/$$/environ            (*@\ding{192}@*)
\end{lstlisting}

\paragraph{任务 2.A: 使用浏览器。}
在上面的代码中，第\ding{192}行打印出当前进程中所有环境变量的内容。通常，如果你使用浏览器访问 CGI 程序，你会看到类似以下的内容。请识别哪些环境变量的值是由浏览器设置的。你可以开启浏览器的HTTP Header Live 扩展来捕获 HTTP 请求，并将请求与服务器打印出的环境变量进行对比。请将你的
调查结果写在实验报告中。

\begin{lstlisting}
****** Environment Variables ******
HTTP_HOST=www.seed-server.com
HTTP_USER_AGENT=Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:83.0) ...
HTTP_ACCEPT=text/html,application/xhtml+xml,application/xml;q=0.9, ...
HTTP_ACCEPT_LANGUAGE=en-US,en;q=0.5
HTTP_ACCEPT_ENCODING=gzip, deflate
...
\end{lstlisting}


\paragraph{任务 2.B: 使用 \texttt{curl}。}
如果我们想将环境变量数据设置为任意值，就必须修改浏览器的行为，这样做会很复杂。幸运的是，有一个命令行工具叫做 \texttt{curl}，它允许用户控制 HTTP 请求中的大部分字段。这里是一些有用的选项：（1）\texttt{-v} 选项可以打印出 HTTP 请求的头部；（2）\texttt{-A}、\texttt{-e} 和 \texttt{-H} 选项可以设置 HTTP 请求头部中的一些字段。你需要弄清楚每个字段的作用。请在实验报告中记录你的
发现。以下是如何使用这些字段的示例：

\begin{lstlisting}
$ curl -v www.seed-server.com/cgi-bin/getenv.cgi
$ curl -A "my data" -v www.seed-server.com/cgi-bin/getenv.cgi
$ curl -e "my data" -v www.seed-server.com/cgi-bin/getenv.cgi
$ curl -H "AAAAAA: BBBBBB" -v www.seed-server.com/cgi-bin/getenv.cgi
\end{lstlisting}

根据本实验，请描述 \texttt{curl} 的哪些选项可以用于将数据注入到目标 CGI 程序的环境变量中。


% -------------------------------------------
% SUBSECTION
% ------------------------------------------- 
\subsection{任务 3: 发起 Shellshock 攻击}

我们现在可以发起 Shellshock 攻击。该攻击不依赖于 CGI 程序中的内容，因为它针对的是 CGI 脚本执行之前调用的 bash 程序。你的任务是通过 URL \url{http://www.seed-server.com/cgi-bin/vul.cgi} 发起攻击，以便让服务器运行任意命令。

如果你的命令有纯文本输出，并且你希望输出返回给你，输出需要遵循如下协议：它应该以
\texttt{Content\_type: text/plain} 开头，后跟一个空行，然后就可以放置纯文本输出。例如，如果你希望服务器返回其文件夹中的文件列表，你的命令应该像下面这样：

\begin{lstlisting}
echo Content-type: text/plain; echo; /bin/ls -l
\end{lstlisting}

在这个任务中，请使用三种不同的方法（即三种不同的 HTTP 头字段）来对目标 CGI 程序发起 Shellshock 攻击。你需要实现以下目标，但对于每个目标，你只需要使用一种方法，但总共需要使用三种不同的方法。

\begin{itemize}
\item 任务 3.A: 让服务器返回 \texttt{/etc/passwd} 文件的内容。

\item 任务 3.B: 让服务器返回其进程的用户 ID。你可以使用 \texttt{/bin/id} 命令打印出 ID 信息。

\item 任务 3.C: 让服务器在\texttt{/tmp}文件夹中创建一个文件。你需要进入容器查看文件是否被创建，或者使用另一个 Shellshock 攻击来列出 \texttt{/tmp} 文件夹中的内容。

\item 任务 3.D: 让服务器删除你刚刚在 \texttt{/tmp} 文件夹中创建的文件。
\end{itemize} 


\paragraph{问题。} 请回答以下问题：
\begin{itemize}
\item 问题 1: 你能否从服务器窃取 \texttt{/etc/shadow} 文件的内容？为什么或者为什么不行？ 任务3.B 中获得的信息应该能给你一些线索。

\item 问题 2: HTTP GET 请求通常会在 URL 中附加数据，放在\texttt{?} 标记后面。我们可以试着用这些数据来发起攻击。在以下示例中，我们在 URL 中附加了一些数据，我们发现这些数据被用来设置成环境变量： 

\begin{lstlisting}
$ curl "http://www.seed-server.com/cgi-bin/getenv.cgi?AAAAA"
...
QUERY_STRING=AAAAA
...
\end{lstlisting}

我们能否使用这种方法发起 Shellshock 攻击？请进行你的实验，并根据实验结果得出结论。

\end{itemize}

  

% -------------------------------------------
% SUBSECTION
% ------------------------------------------- 
\subsection{任务 4: 通过 Shellshock 攻击获取反向 Shell}

Shellshock 漏洞允许攻击者在目标机器上运行任意命令。在实际攻击中，攻击者通常不会将命令固化在攻击中，而是选择运行一个 shell 命令，这样他们就可以使用这个 shell 来运行其他命令。为了实现这一目标，攻击者需要运行一个反向shell。

反向 shell 是一个在受害者机器上运行的 shell 进程，但它从攻击者的机器获取输入并将输出打印在攻击者的机器上。反向 shell 为攻击者提供了在被攻陷的机器上运行 shell 命令的一种便捷方式。如何创建反向shell 的详细说明可以在 SEED 书中找到。我们也在第 \ref{shellshock:sec:reverseshell} 节中做了一些解释。在本任务中，你需要演示如何通过 Shellshock 攻击从受害者那里获得反向 shell。 


% -------------------------------------------
% SUBSECTION
% ------------------------------------------- 
\subsection{任务 5: 使用已修补的Bash}

在该任务中，我们使用一个已经打了补丁的 bash 程序。\texttt{/bin/bash} 程序是修补后的版本。请将CGI 程序的第一行替换为这个程序。重新做一次任务3，描述你的观察结果。 


% *******************************************
% SECTION
% ******************************************* 
\section{指导：创建反向Shell}
\label{shellshock:sec:reverseshell}


\input{\commonfolder/guidelines/reverse_shell}



% *******************************************
% SECTION
% ******************************************* 
\section{提交}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\input{\commonfolder/submission}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


\end{document}
